package com.sun.config;/**
 * @author sun
 * @date 2022/1/4 - 11:21
 */


import com.sun.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

/**
 * @description:会走过滤器UsernamePasswordAuthenticationFilter
 * @author 孙
 * @date 2022/1/4 11:21
 * @version 1.0
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;
    @Autowired
    private UserDetailsServiceImpl userDetailsService;
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;


   @Override
    protected void configure(HttpSecurity http) throws Exception{
        //表单提交
       System.out.println("1111111111111111111");
       //自定义登录页面
        http.formLogin()
                //自定义登录页面
                .loginPage("/showLogin")
        .loginProcessingUrl("/login")
        //登录成功后跳转，必须是post方式
        .successForwardUrl("/tomain")
                //自定义登录成功跳转
        /*.successHandler(new MyForwardAuthenticationSuccessHandler("/main.html"))*/
        //登录失败后跳转，必须是post方式
        .failureForwardUrl("/toerror")
                //自定义失败跳转逻辑
        /*.failureHandler(new MyForwardAuthenticationFailureHandler("/error.html"))*/
        /*.usernameParameter("username1111")
        .passwordParameter("password1111")  自定义登录的参数名*/;



        //授权
        http.authorizeRequests()
                //放行登录页面
                .antMatchers("/showLogin").permitAll()
                //放行失败页面
                //antMatchers的ant表达式：？匹配一个字符  *匹配0个或者多个字符  ** 匹配0个或者多个目录
                /*.antMatchers("/error.html").permitAll()*/
                //permitAll，hasAuthority等底层全部都是通过access实现
                .antMatchers("/error.html").access("permitAll()")
                //放行image下面的全部图片
                /*.antMatchers("/image/**").permitAll()*/
                //.antMatchers("/**/*.jpg").permitAll()
                //正则表达式  设置必须为post请求，后缀为jpg
                /*.regexMatchers(".+[.]jpg").permitAll()*/
                /*.regexMatchers(HttpMethod.POST,".+[.]jpg").permitAll()*/
                //ExpressionUrlAuthorizationConfigurer定义permitAll（）等放行控制
                //只有当前用户拥有admin权限才能访问,严格区分大小写
                /*.antMatchers("/main1.html").hasAuthority("admin111")*/
                //根据角色匹配  不能以ROLE_开头
                /*.antMatchers("/mian1.html").hasRole("abc")*/
                //只能用127.0.0.1来访问，localhost会有问题0:0:0:0:0:0:0:1
                /*.antMatchers("/main1.html").hasIpAddress("127.0.0.1")*/
                /*.antMatchers("/mian1.html").hasAnyAuthority("admin1","admin")*/
                //所有请求都必须被认证，必须登录之后被访问
                .anyRequest().authenticated();
                //自定义请求拦截
                /*.anyRequest().access("@myServiceImpl.hasPermission(request,authentication)");*/

                //异常处理  处理403异常
                http.exceptionHandling()
                        .accessDeniedHandler(new MyAccessDeniedHandler());

                //记住我,,AbstractRememberMeServices包含默认的配置
       http.rememberMe()
               //失效时间，单位秒
               .tokenValiditySeconds(60)
               //自定义登录逻辑
               .userDetailsService(userDetailsService)
               //持久化对象
               .tokenRepository(persistentTokenRepository);

       //退出登录  LogoutConfigurer
       http.logout()
               .logoutSuccessUrl("/login.html");

        //关闭csrf防护,跨站请求伪造
       http.csrf().disable();
    }
    //springsecurity的加密验证方式
    @Bean
    public PasswordEncoder getPw(){
        return new BCryptPasswordEncoder();
    }

    //PersistentTokenRepository的实现类JdbcTokenRepositoryImpl
    @Bean
    public PersistentTokenRepository getPersistentTokenRepository(){
         JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
         jdbcTokenRepository.setDataSource(dataSource);
        //自动创建表，第一次启动时需要，第二次启动需要注释掉，不然会报表存在的错误
         /*jdbcTokenRepository.setCreateTableOnStartup(true);*/
        return jdbcTokenRepository;
    }

}
